package com.ruicar.afs.cloud.afscase.autoaudit.util;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approveocr.entity.ApproveOcrBatch;
import com.ruicar.afs.cloud.afscase.approvetask.entity.CaseApproveRecord;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.LoanServiceBox;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.StepInvoker;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.StepParam;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.Steps;
import com.ruicar.afs.cloud.afscase.common.utils.Const;
import com.ruicar.afs.cloud.afscase.confcaseparam.entity.ConfCaseParam;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseBaseInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseContractInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseBaseInfoService;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseContractInfoService;
import com.ruicar.afs.cloud.afscase.loanapprove.condition.LoanApproveCondition;
import com.ruicar.afs.cloud.afscase.loanapprove.entity.CasePriorityRecord;
import com.ruicar.afs.cloud.afscase.loansuspendrule.entity.LoanSuspendRule;
import com.ruicar.afs.cloud.afscase.paramconfmanagement.entity.CaseConfParam;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.security.service.AfsUser;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.common.rules.RuleHelper;
import com.ruicar.afs.cloud.common.rules.constants.RuleRunEnum;
import com.ruicar.afs.cloud.common.rules.dto.RuleRunResult;
import com.ruicar.afs.cloud.risk.api.enums.tortoise.GwtTortoiseAntiFraudCallStep;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.ruicar.afs.cloud.afscase.processor.enums.LoanSubmitEnum.REPAIR_REPLY;

/**
 * @Description
 * @Author fangchenliang
 * @Date
 */

@UtilityClass
@Slf4j
public class StepUtil {

    final LoanServiceBox serviceBox;

    static {
        serviceBox = SpringContextHolder.getBean(LoanServiceBox.class);
    }

    /**
     * @Description 分单前置步骤执行，影像件ocr识别 -> 玄武大数据 -> 自动打标签
     * @Author fangchenliang
     * @Date
     */
    public void prevSteps(StepParam stepParams) {
        CaseBaseInfoService caseBaseInfoService = serviceBox.getCaseBaseInfoService();
        CaseContractInfoService caseContractInfoService = serviceBox.getCaseContractInfoService();
        if (Objects.isNull(stepParams.getBaseInfo())) {
            CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>lambdaQuery().eq(CaseBaseInfo::getApplyNo, stepParams.getApplyNo()), false);
            CaseContractInfo contractInfo = caseContractInfoService.getOne(Wrappers.<CaseContractInfo>lambdaQuery().eq(CaseContractInfo::getContractNo, stepParams.getContractNo()), false);
            stepParams.setBaseInfo(caseBaseInfo);
            stepParams.setContractInfo(contractInfo);
        }
        Steps.create()
                .then(overdue())
                .then(ocr())
                .then(credit())
                .then(suspend())
                .then(title())
                .err(prevStepErr())
                .end(prevStepEnd())
                .doStep(stepParams, Convert.toInt(stepParams.getContractInfo().getWorkflowPrevStep(), 0));
    }


    /**
     * @Description ocr影像识别
     * @Author fangchenliang
     * @Date 2020/7/8 17:30
     */
    private static StepInvoker ocr() {
        return (stepParam, currentStep) -> {
           try{
               ConfCaseParam confCaseParam = serviceBox.getConfCaseParamService().getOne(Wrappers.<ConfCaseParam>query().lambda()
                    .eq(ConfCaseParam::getParamType,ConfCaseParamTypeEnum.LOAN_OCR_AUTO.getParamType()));
               CaseContractInfo contractInfo = stepParam.getContractInfo();
               if(confCaseParam!=null && confCaseParam.getParamValue().equals("yes") && confCaseParam.getParamStatus().equals("yes")){
                   log.info("合同：{}=>自动执行ocr识别开始...", stepParam.getContractInfo().getContractNo());
                   /**影像识别和自动比对方法待补充*/
                   if (!ObjectUtils.isEmpty(contractInfo)) {
                       ApproveOcrBatch approveOcrBatch =new ApproveOcrBatch();
                       approveOcrBatch.setApplyNo(contractInfo.getApplyNo());
                       approveOcrBatch.setContractNo(contractInfo.getContractNo());
                       /**默认初始化"yes",自动审核不通过会被修改成"no"*/
                       approveOcrBatch.setOcrResult(WhetherEnum.YES.getCode());
                       serviceBox.getApproveOcrBatchService().save(approveOcrBatch);
                       serviceBox.getApproveOcrCompareService().getInvoiceCarOcrCompare(contractInfo,approveOcrBatch);
                       serviceBox.getApproveOcrCompareService().getBankOcrCompare(contractInfo,approveOcrBatch);
                       serviceBox.getApproveOcrCompareService().getIdFrontOcrCompare(contractInfo,approveOcrBatch);

                       /**执行OCR识别成功之后，第一次提交才修改合同状态*/
                       if(contractInfo.getApplyStatus().equals(ApplyStatusEnum.LOAN_WAIT_SUBMIT.getState())){
                           contractInfo.setApplyStatus(ApplyStatusEnum.LOAN_PRE_PROCESS.getState());
                       }
                       contractInfo.setWorkflowPrevStep(currentStep);
                       serviceBox.getCaseContractInfoService().updateById(contractInfo);
                       log.info("合同：{}=>自动执行ocr识别结束...", stepParam.getContractInfo().getContractNo());
                       return true;
                   } else {
                       return false;
                   }
               } else {
                   /**执行OCR识别成功之后，第一次提交才修改合同状态*/
                   if(contractInfo.getApplyStatus().equals(ApplyStatusEnum.LOAN_WAIT_SUBMIT.getState())){
                       contractInfo.setApplyStatus(ApplyStatusEnum.LOAN_PRE_PROCESS.getState());
                   }
                   contractInfo.setWorkflowPrevStep(currentStep);
                   serviceBox.getCaseContractInfoService().updateById(contractInfo);
                   log.info("OCR影像识别配置开关未开启！");
                   return true;
               }
           }catch (Exception e){
               return false;
           }
        };
    }

    /**
     * @Description 自动打标签
     * @Author fangchenliang
     * @Date 2020/7/14 17:30
     */
    private static StepInvoker title() {
        return (stepParam, currentStep) -> {
            try {
                log.info("合同{}:自动打标签开始执行...", stepParam.getContractNo());
                serviceBox.getManualLabelService().loanForLabel(stepParam.getContractNo());
                stepParam.getContractInfo().setWorkflowPrevStep(currentStep);
                serviceBox.getCaseContractInfoService().updateById(stepParam.getContractInfo());
            } catch (Exception e) {
                log.error("自动打标签执行失败.", e);
            }finally {
                return true;
            }
        };
    }

    /**
     * @Description 玄武大数据
     * @Author fangchenliang
     * @Date 2020/7/14 17:30
     */
    private static StepInvoker credit() {
        return (stepParam, currentStep) -> {
            log.info("{}：自动执行玄武征信...", stepParam.getApplyNo());
            try{
                log.info("玄武发欺诈调用触发：applyNo:{},callStep:{}",stepParam.getApplyNo(),GwtTortoiseAntiFraudCallStep.LOAN_APPROVE);
                if (serviceBox.getCaseConfParamService().checkSwitch(Const.PARAMS_SWITCH_XUANWU)) {
                    CaseContractInfo caseContractInfo = stepParam.getContractInfo();
                    if(caseContractInfo.getContractStatus().equals(ContractStatusEnum.create)){
                        serviceBox.getCaseTortoiseService().signalFraudHand(stepParam.getApplyNo(), GwtTortoiseAntiFraudCallStep.LOAN_APPROVE);
                        stepParam.setStillAddStep(true);
                    }
                }else{
                    log.info("玄武开关关闭，反欺诈触发调用取消 applyNo: {}, callStep: {}",stepParam.getApplyNo(),GwtTortoiseAntiFraudCallStep.LOAN_APPROVE);
                }
                return true;
            }catch (Exception e){
                log.error(String.format("反欺诈触发调用失败，applyNo: %s,callStep: %s",stepParam.getApplyNo(),GwtTortoiseAntiFraudCallStep.LOAN_APPROVE.name()),e);
                return false;
            }
        };
    }

    /**
     * @Description 拦截暂停检测
     * @Author rj.zhang
     * @Date 2020/7/30
     */
    private static StepInvoker suspend() {
        return (stepParam, currentStep) -> {
            try {
                CaseContractInfo contractInfo = stepParam.getContractInfo();
                Boolean result =serviceBox.getLoanApproveService().setSuspend(contractInfo);
                if(result.equals(true)){
                    contractInfo.setWorkflowPrevStep(currentStep);
                    serviceBox.getCaseContractInfoService().updateById(contractInfo);
                }
                return result;
            } catch (Exception e) {
                log.error("合同{}:拦截暂停检测执行失败.", e);
                return false;
            }
        };
    }



    /**
     * @Description 分单前置错误处理
     * @Author fangchenliang
     * @Date 2020/7/14 17:30
     */
    private static StepInvoker prevStepErr() {
        return (stepParam, currentStep) -> {
            log.info("合同:{}=>执行错误，当前步骤执行至 " + currentStep, stepParam.getContractNo());
            CaseContractInfo contractInfo = stepParam.getContractInfo();
            if(contractInfo.getApplyStatus().equals(ApplyStatusEnum.LOAN_PRE_PROCESS.getState())){
                contractInfo.setApplyStatus(ApplyStatusEnum.LOAN_QUEUE.getState());
            }
            contractInfo.setWorkflowPrevStep(currentStep);
            serviceBox.getCaseContractInfoService().updateById(contractInfo);
            return true;
        };
    }

    /**
     * @Description 正常结束处理
     * @Author fangchenliang
     * @Date 2020/7/8 17:31
     */
    private static StepInvoker prevStepEnd() {
        return (stepParam, endStep) -> {
            log.info("{}:自动分单前置逻辑执行完毕...", stepParam.getContractNo());
            // 流程退回时修改提交处理
            CaseContractInfo contractInfo = stepParam.getContractInfo();
            if (contractInfo.getApplyStatus().equals(ApplyStatusEnum.LOAN_RETURN.getState())) {
                //更新合同审核状态:补件回复
                contractInfo.setApplyStatus(ApplyStatusEnum.LOAN_REPAIR.getState());
                contractInfo.setIsTop(WhetherEnum.YES.getCode());
                /**优先级小于5（非正常的案件）补件后回复优先级保持不变，只有正常案件才调整为最高优先级*/
//                int priorityValue=Integer.valueOf(contractInfo.getPriority()==null?"5":contractInfo.getPriority());
//                if(priorityValue>=5){
//                    CasePriorityRecord casePriorityRecord=new CasePriorityRecord();
//                    casePriorityRecord.setApplyNo(contractInfo.getApplyNo());
//                    casePriorityRecord.setContractNo(contractInfo.getContractNo());
//                    casePriorityRecord.setPriority(contractInfo.getPriority());
//                    casePriorityRecord.setReason(PriorityReasonEnum.REPAIR.getCode());
//                    casePriorityRecord.setBusiNode(AfsEnumUtil.key(StepSceneEnum.LOAN));
//                    serviceBox.getCasePriorityRecordService().save(casePriorityRecord);
//                }
                contractInfo.setFlowNode(FlowNodeEnum.PRIMARY.getCode());
                contractInfo.setPriority(serviceBox.getCasePriorityChangeService().priorityChange(contractInfo));
                serviceBox.getCaseContractInfoService().updateById(contractInfo);

                //工作流提交流程  保存操作记录
                LoanApproveCondition condition = new LoanApproveCondition();
                condition.setApplyNo(contractInfo.getApplyNo());
                condition.setContractNo(contractInfo.getContractNo());
                condition.setAutoFlag(Boolean.FALSE);
                condition.setApproveType(ApproveTypeEnum.PROCESS.getValue());
                condition.setUseScene(UseSceneEnum.GENERAL_LOAN.getValue());
                condition.setApproveSuggest(AfsEnumUtil.key(REPAIR_REPLY));
                condition.setFlowNode(FlowNodeEnum.CHANNEL.getCode());
                try {
                    serviceBox.getLoanWorkflowService().submitWorkflowByScheduleInfo(condition);
                    serviceBox.getCaseStepParamService().clear(contractInfo.getApplyNo(),StepSceneEnum.LOAN);
                    return true;
                } catch (Exception e) {
                    log.error("合同：{}=>{}流程提交失败：{}", stepParam.getContractNo(), AfsEnumUtil.desc(REPAIR_REPLY), e);
                    return false;
                }
            } else {
                if(contractInfo.getApplyStatus().equals(ApplyStatusEnum.LOAN_PRE_PROCESS.getState())){
                    contractInfo.setApplyStatus(ApplyStatusEnum.LOAN_QUEUE.getState());
                }
                contractInfo.setWorkflowPrevStep(endStep);
                serviceBox.getCaseContractInfoService().updateById(contractInfo);
                serviceBox.getCaseStepParamService().clear(contractInfo.getApplyNo(),StepSceneEnum.LOAN);
                return true;
            }
        };
    }

    /**
     * @param
     * @Description 发起Gps审核流程
     * @Author yk.Li
     * @date 2020/7/29
     */
    private StepInvoker startGpsAudit() {
        return (stepParam, currentStep) -> {
            try {
                Assert.isTrue(null != stepParam && null != stepParam.getContractInfo(),">>>>>执行GPS审核流程步骤异常...");
                if (null != stepParam.getContractInfo().getGpsWorkflowStatus()) {
                    log.info("合同:{}=>GPS退回合作商提交...", stepParam.getContractNo());
                }
                log.info("合同:{}=>发起GPS流程审核START...", stepParam.getContractNo());
                //  serviceBox.getGpsManageService().startGpsWorkflow(stepParam.getContractNo());
                log.info("合同:{}=>发起GPS流程审核END...", stepParam.getContractNo());
                // 发起GPS初始化
                // serviceBox.getGpsManageService().getAllOrderInfoByAppCode(stepParam.getContractNo());
            } catch (Exception e) {
                log.error("合同:{}=>发起GPS流程审核ERROR...", stepParam.getContractNo(), e);
            }finally {
                return true;
            }
        };
    }

    public StepInvoker overdue(){
        return (stepParam, currentStep) -> {
            try {
                if(serviceBox.getCaseConfParamService().checkSwitch(Const.ARCHIVE_OVERDUE_SWITCH)) {
                        Assert.isTrue(null != stepParam && null != stepParam.getContractInfo(), ">>>>>执行超期异常步骤异常...");
                        return serviceBox.getArchiveApiService().setOverdue(stepParam.getContractInfo().getContractNo());
                }else {
                    log.info("归档超期开关未启用，跳过判断！");
                }
            } catch (Exception e) {
                log.error("合同：{}=>超期判断ERROR...", stepParam.getContractNo(), e);
            }finally {
                return true;
            }
        };
    }
}
